home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / makeindex / genind.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-04-26  |  7.2 KB  |  342 lines

  1. /*
  2.  *
  3.  * Copyright (C) 1987     Pehong Chen    (phc@renoir.berkeley.edu)
  4.  * Computer Science Division
  5.  * University of California, Berkeley
  6.  *
  7.  */
  8.  
  9. #include        "mkind.h"
  10. #include        "genind.h"
  11.  
  12. static    FIELD_PTR    curr = NULL;
  13. static    FIELD_PTR    prev = NULL;
  14. static    FIELD_PTR    begin = NULL;
  15. static    FIELD_PTR    end = NULL;
  16. static    FIELD_PTR    range_ptr;
  17. static    int        level = 0;
  18. static    int        prev_level = 0;
  19. static    char        *encap = NULL;
  20. static    char        *prev_encap = NULL;
  21. static    int        in_range = FALSE;
  22. static    int        encap_range = FALSE;
  23. static    int        range_lc;
  24. static    char        buff[2*LINE_MAX];
  25. static    char        line[2*LINE_MAX];    /* output buffer */
  26. static    int        ind_lc = 0;        /* overall line count */
  27. static    int        ind_ec = 0;        /* erroneous line count */
  28. static    int        ind_indent;
  29.  
  30.  
  31. void
  32. gen_ind()
  33. {
  34.     int        n;
  35.     int        tmp_lc;
  36.  
  37.     MESSAGE("Generating output file %s...", ind_fn);
  38.     PUT(preamble);
  39.     ind_lc += prelen;
  40.     if (init_page)
  41.         insert_page();
  42.  
  43.     /* reset counters for putting out dots */
  44.     idx_dc = 0;
  45.     for (n = 0; n < idx_gt; n++) {
  46.         if (idx_key[n]->type != DUPLICATE)
  47.             if (make_entry(n)) {
  48.                 IDX_DOT(DOT_MAX);
  49.             }
  50.     }
  51.  
  52.     tmp_lc = ind_lc;
  53.     if (in_range) {
  54.         curr = range_ptr;
  55.         IND_ERROR("Unmatched range opening operator %c.\n", idx_ropen);
  56.     }
  57.  
  58.     prev = curr;
  59.     flush_line(TRUE);
  60.     PUT(postamble);
  61.     tmp_lc = ind_lc + postlen;
  62.     if (ind_ec == 1) {
  63.         DONE(tmp_lc, "lines written", ind_ec, "warning");
  64.     } else {
  65.         DONE(tmp_lc, "lines written", ind_ec, "warnings");
  66.     }
  67. }
  68.  
  69.  
  70. static int
  71. make_entry(n)
  72.     int            n;
  73. {
  74.     int            let;
  75.  
  76.     /* determine current and previous pointer */
  77.     prev = curr;
  78.     curr = idx_key[n];
  79.  
  80.     /* check if current entry is in range */
  81.     if ((*curr->encap == idx_ropen) || (*curr->encap == idx_rclose))
  82.         encap = &(curr->encap[1]);
  83.     else
  84.         encap = curr->encap;
  85.  
  86.     /* determine the current nesting level */
  87.     if (n == 0) {
  88.         prev_level = level = 0;
  89.         make_item();
  90.         let = *curr->sf[0];
  91.         LETTERHEAD;
  92.     } else {
  93.         prev_level = level;
  94.         for (level = 0; level < FIELD_MAX; level++)
  95.                 if (STRNEQ(curr->sf[level], prev->sf[level]) ||
  96.                     STRNEQ(curr->af[level], prev->af[level]))
  97.                     break;
  98.         if (level < FIELD_MAX)
  99.             new_entry();
  100.         else
  101.             old_entry();
  102.     }
  103.  
  104.     if (*curr->encap == idx_ropen)
  105.         if (in_range) {
  106.             IND_ERROR("Extra range opening operator %c.\n", idx_ropen);
  107.         } else {
  108.             in_range = TRUE;
  109.             range_ptr = curr;
  110.             range_lc = ind_lc;
  111.         }
  112.     else if (*curr->encap == idx_rclose)
  113.         if (in_range) {
  114.             in_range = FALSE;
  115.             if (STRNEQ(&(curr->encap[1]), "") &&
  116.                 STRNEQ(prev_encap, &(curr->encap[1]))) {
  117.                 IND_ERROR("Range closing operator has an inconsitent encapsulator %s.\n", &(curr->encap[1]));
  118.             }
  119.         } else {
  120.             IND_ERROR("Unmatched range closing operator %c.\n", idx_rclose);
  121.         }
  122.     else if ((*curr->encap != NULL) &&
  123.          STRNEQ(curr->encap, prev_encap) && in_range)
  124.         IND_ERROR("Inconsistent page encapsulator %s within range.\n", curr->encap);
  125.     return (1);
  126. }
  127.  
  128.  
  129. static void
  130. make_item()
  131. {
  132.     int         i;
  133.  
  134.     if (level > prev_level) {
  135.         /* ascending level */
  136.         if (*curr->af[level] == NULL)
  137.             sprintf(line, "%s%s", item_u[level], curr->sf[level]);
  138.         else
  139.             sprintf(line, "%s%s", item_u[level], curr->af[level]);
  140.         ind_lc += ilen_u[level];
  141.     } else {
  142.         /* same or descending level */
  143.         if (*curr->af[level] == NULL)
  144.             sprintf(line, "%s%s", item_r[level], curr->sf[level]);
  145.         else
  146.             sprintf(line, "%s%s", item_r[level], curr->af[level]);
  147.         ind_lc += ilen_r[level];
  148.     }
  149.  
  150.     i = level + 1;
  151.     while (i < FIELD_MAX && *curr->sf[i] != NULL) {
  152.         PUT(line);
  153.         if (*curr->af[i] == NULL)
  154.             sprintf(line, "%s%s", item_x[i], curr->sf[i]);
  155.         else
  156.             sprintf(line, "%s%s", item_x[i], curr->af[i]);
  157.         ind_lc += ilen_x[i];
  158.         i++;
  159.     }
  160.  
  161.     ind_indent = 0;
  162.     strcat(line, delim_p[level]);
  163.     SAVE;
  164. }
  165.  
  166.  
  167. static void
  168. new_entry()
  169. {
  170.     char            let;
  171.     FIELD_PTR        ptr;
  172.  
  173.     if (in_range) {
  174.         ptr = curr;
  175.         curr = range_ptr;
  176.         IND_ERROR("Unmatched range opening operator %c.\n", idx_ropen);
  177.         in_range = FALSE;
  178.         curr = ptr;
  179.     }
  180.  
  181.     flush_line(TRUE);
  182.  
  183.     /* beginning of a new group? */
  184.     if (((curr->group != ALPHA) && (curr->group != prev->group)) ||
  185.         ((curr->group == ALPHA) &&
  186.          ((let = TOLOWER(curr->sf[0][0])) != (TOLOWER(prev->sf[0][0]))))) {
  187.         PUT(group_skip);
  188.         ind_lc += skiplen;
  189.         /* beginning of a new letter? */
  190.         LETTERHEAD;
  191.     }
  192.     make_item();
  193. }
  194.  
  195.  
  196. static void
  197. old_entry()
  198. {
  199.     int        diff;
  200.  
  201.     /* current entry identical to previous one: append pages */
  202.     diff = page_diff(end, curr);
  203.     if ((prev->type == curr->type) && (diff != -1) &&
  204.         (((diff == 0) && (prev_encap != NULL) && STREQ(encap, prev_encap)) ||
  205.          (merge_page && (diff == 1) &&
  206.           (prev_encap != NULL) && STREQ(encap, prev_encap)) ||
  207.          in_range)) {
  208.         end = curr;
  209.         /* extract in-range encaps out */
  210.         if (in_range &&
  211.             (*curr->encap != NULL) &&
  212.             (*curr->encap != idx_rclose) &&
  213.             STRNEQ(curr->encap, prev_encap)) {
  214.             sprintf(buff, "%s%s%s%s%s", encap_p, curr->encap,
  215.                 encap_i, curr->lpg, encap_s);
  216.             wrap_line(FALSE);
  217.         }
  218.         if (in_range)
  219.             encap_range = TRUE;
  220.     } else {
  221.         flush_line(FALSE);
  222.         if ((diff == 0) && (prev->type == curr->type)) {
  223.             IND_ERROR("Conflicting entries: multiple encaps for the same page under same key.\n", "");
  224.         } else if (in_range && (prev->type != curr->type)) {
  225.             IND_ERROR("Illegal range formation: starting & ending pages are of different types.\n", "");
  226.         } else if (in_range && (diff == -1)) {
  227.             IND_ERROR("Illegal range formation: starting & ending pages cross chap/sec breaks.\n", "");
  228.         }
  229.         SAVE;
  230.     }
  231. }
  232.  
  233.  
  234. static int
  235. page_diff(a, b)
  236.     FIELD_PTR    a;
  237.     FIELD_PTR    b;
  238. {
  239.     short        i;
  240.  
  241.     if (a->count != b->count)
  242.         return (-1);
  243.     for (i = 0; i < a->count-1; i++)
  244.         if (a->npg[i] != b->npg[i])
  245.             return (-1);
  246.     return (b->npg[b->count-1] - a->npg[a->count-1]);
  247. }
  248.  
  249.  
  250. static void
  251. flush_line(print)
  252.     int        print;
  253. {
  254.     char        tmp[LINE_MAX];
  255.  
  256.     if (page_diff(begin, end) != 0)
  257.         if (encap_range || (page_diff(begin, prev) > 1)) {
  258.             sprintf(buff, "%s%s%s", begin->lpg, delim_r, end->lpg);
  259.             encap_range = FALSE;
  260.         } else
  261.             sprintf(buff, "%s%s%s", begin->lpg, delim_n, end->lpg);
  262.      else
  263.         strcpy(buff, begin->lpg);
  264.  
  265.     if (*prev_encap != NULL) {
  266.         strcpy(tmp, buff);
  267.         sprintf(buff, "%s%s%s%s%s", encap_p, prev_encap, encap_i, tmp, encap_s);
  268.     }
  269.  
  270.     wrap_line(print);
  271. }
  272.  
  273.  
  274. static void
  275. wrap_line(print)
  276.     int        print;
  277. {
  278.     int        len;
  279.  
  280.     len = strlen(line) + strlen(buff) + ind_indent;
  281.     if (print) {
  282.         if (len > linemax) {
  283.             PUTLN(line);
  284.             PUT(indent_space);
  285.             ind_indent = indent_length;
  286.         } else
  287.             PUT(line);
  288.         PUT(buff);
  289.     } else {
  290.         if (len > linemax) {
  291.             PUTLN(line);
  292.             sprintf(line, "%s%s%s", indent_space, buff, delim_n);
  293.             ind_indent = indent_length;
  294.         } else {
  295.             strcat(buff, delim_n);
  296.             strcat(line, buff);
  297.         }
  298.     }
  299. }
  300.  
  301.  
  302. static void
  303. insert_page()
  304. {
  305.     int        i = 0;
  306.     int        j = 0;
  307.     int        page = 0;
  308.  
  309.     if (even_odd >= 0) {
  310.         /* find the rightmost digit */
  311.         while (pageno[i++] != NULL);
  312.         j = --i;
  313.         /* find the leftmost digit */
  314.         while (isdigit(pageno[--i]) && i > 0);
  315.         if (! isdigit(pageno[i]))
  316.             i++;
  317.         /* convert page from literal to numeric */
  318.         page = strtoint(&pageno[i]) + 1;
  319.         /* check even-odd numbering */
  320.         if (((even_odd == 1) && (page%2 == 0)) || ((even_odd == 2) && (page%2 == 1)))
  321.                 page++;
  322.         pageno[j+1] = NULL;
  323.         /* convert page back to literal */
  324.         while (page >= 10) {
  325.             pageno[j--] = TOASCII(page%10);
  326.             page = page / 10;
  327.         }
  328.         pageno[j] = TOASCII(page);
  329.         if (i < j) {
  330.             while (pageno[j] != NULL)
  331.                 pageno[i++] = pageno[j++];
  332.             pageno[i] = NULL;
  333.         }
  334.     }
  335.  
  336.     PUT(setpage_open);
  337.     PUT(pageno);
  338.     PUT(setpage_close);
  339.     ind_lc += setpagelen;
  340. }
  341.  
  342.